home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 203_01 / yam4.c < prev    next >
Encoding:
C/C++ Source or Header  |  1980-01-01  |  6.4 KB  |  306 lines

  1. /*
  2. $title ('yam4.c: CIS A protocol')
  3. $date (20 mar 85)
  4. */
  5. /*
  6.  *
  7.  * Support for Compuserve CIS A protocol
  8.  * file-upload and file-download functions
  9.  * called from term() when ascii SI is received.
  10.  *
  11.  * It seems that the CIS protocol isn't quite as simple as YAM4.C
  12.  * was lead to beleive! 1) The SI and SO may have the high-order
  13.  * bit on, as SI and SO without the high order bit on are used to
  14.  * control external network echoing. 2) If you R FILTRN, then a
  15.  * "redundant" SI is issued when FILTRN transfers control to
  16.  * XFTRAN without sending an SO. 3) Sometimes CIS ends a transfer
  17.  * without any SO at all, just starts sending (with a blank).
  18.  * 5) The fixes therein allow downloading from Micro-quote
  19.  * via TymNet.  DAVID WELCH
  20.  */
  21.  
  22. #include "yam.h"
  23.  
  24. FLAG CISasc;            /* CIS xfer is in ascii mode */
  25. char ciscursec;        /* Sector number just received by cisgetsec() */
  26.  
  27. cispa()
  28. {
  29.     register char *p;
  30.  
  31.     for(;;) {
  32.         switch( firstch=readbyte(400)) {
  33.           case ESC:
  34.             switch(firstch=readbyte(400)) {
  35.             case 'I':
  36.                 pstat("CIS-IDENT");
  37.                 p = MYSYSTEM;
  38.                 while( *p)
  39.                     sendbyte( *p++);
  40.                 continue;
  41.             case 'A':
  42.                 if(cisxfer() != ERROR)
  43.                     continue;
  44.                 sendline(NAK); return ERROR;
  45.             default:
  46.                 break;
  47.             }
  48.         default:
  49.             lprintf("Bad CIS request 0%o\n", firstch);
  50.             return ERROR;
  51.         case '\n':
  52.         case SO:
  53.         case (SO | 0x80):
  54.         case ' ':
  55.             return OK;
  56.         case SI:
  57.         case (SI | 0x80):
  58.             break;
  59.         }
  60.     }
  61. }
  62.  
  63. /*
  64.  * get file request from host and perform the transfer
  65.  */
  66. cisxfer()
  67. {
  68.     char *p;
  69.     CISasc = FALSE;
  70.     if(cisgetsec(Utility.ubuf, (PATHLEN+3)) <= 0)
  71.         return ERROR;
  72.     if(p=index('\r', Utility.ubuf))
  73.         *p = 0;
  74.     CISasc = (Utility.ubuf[1] == 'A');
  75.  
  76.     if(Utility.ubuf[0] == 'U') {
  77.         if(opentx( &Utility.ubuf[2]) == ERROR)
  78.             return ERROR;
  79.         sendbyte('.');
  80.         if(readbyte(400) != '.'  ||  sendcis() == ERROR) {
  81.             closetx(FALSE); return ERROR;
  82.         }
  83.         closetx(TRUE); return OK;
  84.     }
  85.     else if(Utility.ubuf[0] == 'D') {
  86.         if(openrx( &Utility.ubuf[2]) == ERROR) {
  87.             return ERROR;
  88.         }
  89.         sendbyte('.');
  90.         return getcis();
  91.     }
  92.     else
  93.         return ERROR;
  94. }
  95.  
  96. sendcis()
  97. {
  98.     unsigned nchars;
  99.  
  100.     nchars=0;
  101.     while((wcj=filbcis(Utility.ubuf)) > 0) {
  102.         pstat("Char %u", nchars);
  103.         if(scisrec(Utility.ubuf, wcj)==ERROR)
  104.             return ERROR;
  105.         nchars += wcj;
  106.     }
  107.     return scisrec(0,0);    /* send special EOT record */
  108. }
  109.  
  110. /*
  111.  * fill p with at most 256 chars not incl EOF
  112.  * returns number of chars fetched, 0 for end of file
  113.  */
  114. filbcis(p)
  115. char *p;
  116. {
  117.     int c;
  118.     int count;
  119.     for( count=0; count< 256; ++count) {
  120.         if((c=getc(fin)) == EOF)
  121.             break;
  122.         if(CISasc && c == CPMEOF) {
  123.             ungetc(CPMEOF, fin); break;
  124.         }
  125.         *p++ =c;
  126.     }
  127.     return count;
  128. }
  129. /*
  130.  * send a record at buf with length len to CIS
  131.  * return ERROR if unsuccessful
  132.  * Special case: len==0 causes EOT record to be sent
  133.  *          instead of buffer contents
  134.  */
  135. scisrec( buf, len)
  136. char *buf;
  137. {
  138.     char *p;
  139.     int count;
  140.     int retry;
  141.     if( ++ciscursec > '9')
  142.         ciscursec = '0';
  143.     for(retry = 5; --retry; ++toterrs) {
  144.         p = buf; sendbyte(SOH);
  145.         sendbyte(oldcrc=ciscursec);
  146.         if(len==0) {
  147.             sendbyte(firstch=EOT);
  148.             ucksum();
  149.         } else
  150.             for(count=len; --count >=0;) {
  151.                 firstch = *p++ & 0377;
  152.                 ucksum();
  153.                 sendmsk(firstch);
  154.                 if(CISasc)
  155.                     putcty(firstch);
  156.             }
  157.         sendbyte(ETX);
  158.         sendmsk(oldcrc);
  159.         if((firstch=readbyte(400)) == '.')
  160.             return OK;
  161.         if (CISasc)
  162.             lprintf("\n");
  163.         lprintf("Got 0%o for record ACK\n", firstch);
  164.         if(firstch < 0)
  165.             return ERROR;
  166.     }
  167.     return ERROR;
  168. }
  169.  
  170. /*
  171.  * send most control charsacters as DLE sequence
  172.  * except for BEL to CR inclusive
  173.  */
  174. sendmsk(c)
  175. unsigned c;
  176. {
  177.     c &= 0377;        /* in case of sign extension */
  178.     if( c < 7 || (c < 0x20 && c > 0x0D)) {
  179.         sendbyte(DLE);
  180.         sendbyte(c | 0x40);
  181.     }
  182.     else
  183.         sendbyte(c);
  184. }
  185.  
  186. /*
  187.  * get (download) a file with CIS A protocol
  188.  */
  189. getcis()
  190. {
  191.     char cursec;
  192.     char *p;
  193.     unsigned nchars;
  194.  
  195.     cursec = '1'; nchars=0;
  196.     for(;;) {
  197.         pstat("Char %u", nchars);
  198. doagain:
  199.         if((wcj=cisgetsec(Utility.ubuf, KSIZE)) <= 0)
  200.             break;
  201.         if(ciscursec==EOT)
  202.             break;
  203.         if(ciscursec == cursec) {
  204.             sendbyte('.');
  205.             goto doagain;
  206.         }
  207.         if(ciscursec == cursec+1 ||
  208.           (cursec == '9' && ciscursec == '0') ) {
  209.             nchars += wcj;
  210.             for(p=Utility.ubuf; --wcj >= 0; )
  211.                 fputc( *p++, fout);
  212.             if( ++cursec > '9')
  213.                 cursec = '0';
  214.             sendbyte('.');
  215.         }
  216.         else {
  217.             if (CISasc)
  218.                 lprintf("\n");
  219.             lprintf("Got record 0%o expecting 0%o\n",
  220.               ciscursec, cursec);
  221.             break;
  222.         }
  223.     }
  224.     lprintf("%u Characters Received ", nchars);
  225.     if(ciscursec != EOT) {
  226.         closerx(TRUE);    return ERROR;
  227.     }
  228.     if(CISasc)
  229.         fputc(CPMEOF, fout);
  230.     closerx(FALSE); sendbyte('.'); return OK;
  231. }
  232. /*
  233.  * gets a CIS A protocol record into buf.  Record number returned in global
  234.  * ciscursec, which equals EOT for EOT record (end of file).  Returns number
  235.  * of characters read.  Returns ERROR if too many chars received.
  236.  * no retry count; it is assumed that sender will send NAK to abort
  237.  * (will abort on timeout)
  238.  * The acknowledge is NOT sent by cisgetsec; the caller must send a '.'
  239.  * when it is ready to proceed.
  240.  */
  241. cisgetsec(buf, maxcount)
  242. char *buf;
  243. {
  244.     char *p;
  245.     int count;
  246.  
  247. reread:
  248.     for(;;) {
  249.         if((firstch=readbyte(400)) == SOH)
  250.             break;
  251.         if(firstch==TIMEOUT)
  252.             return ERROR;
  253.         if(firstch==NAK)
  254.             return ERROR;
  255.     }
  256.     ciscursec = oldcrc = readbyte(400);
  257.     for(p=buf, count=0; ;) {
  258.         switch(firstch=readbyte(400)) {
  259.         case TIMEOUT:
  260.               return ERROR;
  261.         case NAK:
  262.             return ERROR;
  263.         case ETX:
  264.             if((firstch=readbyte(400))==TIMEOUT)
  265.                 return ERROR;
  266.             if(firstch==DLE) {
  267.                 if((firstch=readbyte(400))==TIMEOUT)
  268.                     return ERROR;
  269.                 firstch &= 037;
  270.             }
  271.             if(firstch == oldcrc)
  272.                 return count;
  273.             if (CISasc)
  274.                 lprintf("\n");
  275.             lprintf("Error Checksum=0%o Got 0%o \n",
  276.               oldcrc, firstch);
  277.             ++toterrs; sendbyte('/'); goto reread;
  278.         case EOT:
  279.             ciscursec = EOT; break;
  280.         case DLE:
  281.             if((firstch=readbyte(400))==TIMEOUT)
  282.                 return ERROR;
  283.             firstch &= 037;
  284.         }
  285.         if(++count > maxcount)
  286.             return ERROR;
  287.         *p++ = firstch;
  288.         if(CISasc)
  289.             putcty(firstch);
  290.         ucksum();
  291.     }
  292. }
  293. /*
  294.  * ucksum updates oldcrc with firstch
  295.  * CIS uses rotate left, NOT shift left as per protocol.cis
  296.  */
  297. ucksum()
  298. {
  299.     oldcrc += oldcrc;
  300.     if(oldcrc & 0400)
  301.         ++oldcrc;
  302.     if( (oldcrc = (oldcrc & 0377) + firstch) & 0400)
  303.         ++oldcrc;
  304.     oldcrc &= 0377;
  305. }
  306.